﻿using Blm.Utils.Extensions;
using Language.Resource;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using Newtonsoft.Json.Linq;
using Swashbuckle.AspNetCore.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using VisionCloud.Api.Common;
using VisionCloud.Domain.Common;
using VisionCloud.Domain.Data;
using VisionCloud.Domain.DtoModel.Inner;
using VisionCloud.Domain.DtoModel.Ms;
using VisionCloud.Domain.DtoModel.Sys;
using VisionCloud.Domain.Extension;
using VisionCloud.Domain.Filters;
using VisionCloud.Service.Fms;
using VisionCloud.Service.Ms;
using VisionCloud.Service.Rs;
using VisionCloud.Utility.Extensions;

namespace VisionCloud.Api.Controllers.Ms
{
    /// <summary>
    /// 项目管理相关
    /// </summary>
    [SystemModule("项目管理相关")]
    [ApiAuthorize(PolicyEnum.RequireRolePermission)]
    [ApiVersion("1.0")]
    [Route("api/ms/[controller]/[Action]")]
    [ApiExplorerSettings(GroupName = "项目管理相关")]
    public class ProjectController : ApiBaseController
    {
        /// <summary>
        /// ProjectService
        /// </summary>
        public ProjectService ProjectService { get; set; }

        /// <summary>
        /// 项目服务
        /// </summary>
        public ProjectDCService ProjectDCService { get; set; }

        /// <summary>
        /// 户型图服务
        /// </summary>
        public HouseMapService HouseMapService { get; set; }

        /// <summary>
        /// 测量项服务
        /// </summary>
        public MeasureTemplateService MeasureTemplateService { get; set; }

        /// <summary>
        /// 多语言资源
        /// </summary>
        public IStringLocalizer<ControllerResource> Localizer { get; set; }

        /// <summary>
        /// 公共多语言资源
        /// </summary>
        public IStringLocalizer<CommonResource> CommonLocalizer { get; set; }

        public RsWorkOrderMapService RsWorkOrderMapService { get; set; }

        /// <summary>
        /// 获取项目的数据中台Code
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "获取项目的数据中台Code" })]
        public async Task<ApiResult> GetProjectDCCode(FindWithFloorRqDto request)
        {
            return await TryCatchAsync(ProjectDCService.GetProjectDCCode(request));
        }

        #region 项目管理

        /// <summary>
        /// 获取项目分页
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> GetList(MsProjectListCondition model)
        {
            return await TryCatchAsync(ProjectService.GetList(model));
        }

        /// <summary>
        /// 项目管理列表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> GetPage(MsProjectCondition model)
        {
            return await TryCatchAsync(ProjectService.GetPage(model));
        }

        /// <summary>
        /// 测量服务-获取项目分页
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "测量服务" })]
        public async Task<ApiResult> MsGetProjectInfo(MsProjectCondition model)
        {
            return await TryCatchAsync(ProjectService.GetProjectInfo(model));
        }

        /// <summary>
        /// 新增项目
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        [ApiAuthorize(PolicyEnum.RequireCompanyManager)]
        public async Task<ApiResult> Add(MsProjectDto model)
        {
            return await TryCatchAsync(ProjectService.Add(model));
        }

        /// <summary>
        /// 更新项目信息数据-- 楼层
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> Update(MsProjectDto model)
        {
            return await TryCatchAsync(ProjectService.Update(model));
        }

        /// <summary>
        /// 保存项目人员关系
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> SaveProjectUser(UserProjectViewModel model)
        {
            return await TryCatchAsync(ProjectService.SaveProjectUser(model));
        }

        /// <summary>
        /// 分配项目
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> SaveUserToProject(UserProjectViewModel model)
        {
            model.IP = HttpContext.GetClientUserIp();
            return await TryCatchAsync(ProjectService.SaveUserToProject(model));
        }

        /// <summary>
        /// 删除项目信息数据
        /// </summary>
        /// <param name="model">ProjectId</param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> Delete(ProjectIDRequiredDto model)
        {
            var ip = HttpContext.GetClientUserIp();
            return await TryCatchAsync(Task.Run(async () =>
            {
                await ProjectService.DeleteProjectCache(model.ProjectId);
                _ = await ProjectService.SendMsgAfterDel(model.ProjectId, ip);
                await ProjectService.Delete(model.ProjectId);
                await HouseMapService.RemoveHouseMapsByProjectId(model.ProjectId);
                // 逻辑删除项目关联工单
                await RsWorkOrderMapService.Delete(model.ProjectId);
            }));
        }

        /// <summary>
        /// 发布项目
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> publiceProject(ProjectIDRequiredDto model)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                var ip = HttpContext.GetClientUserIp();
                await ProjectService.PubliceProject(ip, model.ProjectId);
            }));
        }

        /// <summary>
        /// 获取项目信息
        /// </summary>
        /// <param name="ms"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> GetProjectInfo(MsCondition ms)
        {
            return await TryCatchAsync(ProjectService.GetProjectInfo(ms.ProjectId));
        }

        /// <summary>
        /// 禁用项目
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, SwaggerOperation(Tags = new[] { "项目管理" })]
        public async Task<ApiResult> Disable(ProjectIDRequiredDto model)
        {
            return await TryCatchAsync(ProjectService.SetDisable(model.ProjectId));
        }

        #endregion 项目管理

        /// <summary>
        /// 户型图、dxf、json文件上传
        /// </summary>
        /// <param name="formCollection"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> HouseMapUpload(IFormCollection formCollection)
        {
            var dataDatyString = formCollection["DataType"].ToString();
            var model = new UploadHouseMapModel
            {
                ProjectId = string.IsNullOrWhiteSpace(formCollection["ProjectId"]) ? Guid.Empty : new Guid(formCollection["ProjectId"]),
                Name = formCollection["Name"],
                Maps = formCollection.Files,
                MapType = int.Parse(formCollection["MapType"]),
                DataType = string.IsNullOrEmpty(dataDatyString) ? 0 : int.Parse(dataDatyString)
            };

            await Contracts.Frequency($"housemap_upload_limit_{model.ProjectId}", 1, TimeSpan.FromSeconds(3), CommonLocalizer["YB0449"].Value);

            return await HouseMapService.UploadHouseMapFile(model);
        }

        /// <summary>
        /// 户型图列表
        /// </summary>
        /// <param name="condition">字段 ProjectId</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> HouseMapList(MsHouseMapCondition condition)
        {
            return await TryCatchAsync(HouseMapService.GetProjectHouseMap(condition));
        }

        #region 编辑户型图名称

        /// <summary>
        /// 编辑户型图名称
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> HouseMapUpdate(ProjectHouseMap model)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                await HouseMapService.HouseMapUpdate(model);
                return await HouseMapService.GetHouseMapById(model.HouseMapId);
            }));
        }

        /// <summary>
        /// 通过Dxf文件调用自动标注算法更新户型图
        /// </summary>
        /// <param name="formCollection"></param>
        /// <remarks>
        /// 入参说明：
        /// HouseMapId：户型图Id
        /// file：文件集合
        /// </remarks>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> HouseMapUpdateByDxf(IFormCollection formCollection)
        {
            var model = new HouseMapUpdateByDxfDto
            {
                HouseMapId = string.IsNullOrWhiteSpace(formCollection["HouseMapId"]) ? Guid.Empty : new Guid(formCollection["HouseMapId"]),
                Maps = formCollection.Files
            };

            await Contracts.Frequency($"housemap_update_limit_{model.HouseMapId}", 1, TimeSpan.FromSeconds(3), CommonLocalizer["YB0449"].Value);
            await Contracts.Frequency($"housemap_update_limit_all_{Guid.NewGuid()}", 10, TimeSpan.FromSeconds(90), CommonLocalizer["YB0449"].Value);

            return await HouseMapService.UpdateHouseMapByDxf(model);
        }

        /// <summary>
        /// 修改户型图名称
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> HouseMapUpdateName(ProjectHouseMap model)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                await HouseMapService.HouseMapUpdateName(model);
                return await HouseMapService.GetHouseMapById(model.HouseMapId);
            }));
        }

        /// <summary>
        /// 新增/更新测量项设计值模板
        /// </summary>
        /// <param name="models">测量项对象列表</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> UpdateMeasureTemplate(List<MsMeasureTemplateDto> models)
        {
            return await TryCatchAsync(MeasureTemplateService.UpdateMeasureTemplate(models));
        }

        /// <summary>
        /// 新增/更新测量项设计值模板
        /// </summary>
        /// <param name="models">测量项对象列表</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> updateHouseTypeTemplate(MSHouseTypeTemplateDTO models)
        {
            return await TryCatchAsync(MeasureTemplateService.UpdateHouseTypeTemplate(models));
        }

        /// <summary>
        /// 复制户型图
        /// </summary>
        /// <param name="model">户型图对象</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> CopyHouseMap(ProjectHouseMap model)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                if (model.ProjectId == Guid.Empty)
                {
                    throw new OperationException(Localizer["YB0008"].Value);
                }
                if (model.HouseMapId == Guid.Empty)
                {
                    throw new OperationException(Localizer["YB0009"].Value);
                }
                if (string.IsNullOrEmpty(model.Name))
                {
                    throw new OperationException(Localizer["YB0010"].Value);
                }
                if (!System.Text.RegularExpressions.Regex.IsMatch(model.Name, @"^[\u4e00-\u9fa5_a-zA-Z0-9]+$"))
                {
                    throw new OperationException(Localizer["YB0011"].Value);
                }
                await HouseMapService.CopyHouseMapUpdate(model);
                var condition = new MsHouseMapCondition() { ProjectId = model.ProjectId };
                return await HouseMapService.GetProjectHouseMap(condition);
            }));
        }

        /// <summary>
        /// 根据户型图Id获取测量项模板
        /// </summary>
        /// <param name="obj">户型图Id:houseMapId</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetMeasureItemTemplate(JObject obj)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                var houseMapId = obj.GetAndCheck<Guid>("houseMapId");
                return await MeasureTemplateService.GetMeasureItemTemplate(houseMapId);
            }));
        }

        #endregion 编辑户型图名称

        /// <summary>
        /// 任务获取项目的楼栋下拉选项
        /// </summary>
        /// <param name="obj">字段 ProjectId,addDefault=false</param>
        /// <returns></returns>
        [HttpPost]
        public Task<ApiResult> GetProjectBuilding(JObject obj)
        {
            return TryCatch(async () =>
           {
               var projectId = obj.GetAndCheck<Guid>("ProjectId");
               var addDefault = obj.GetAndCheck<bool>("addDefault", false, false);
               var list = ProjectService.GetProjectBuilding(projectId).Result ?? new List<Detail>();
               var items = list.Select(s => new SelectItem(s.Building, s.Building.ToString())).ToArray();
               return SelectItem.ToItems(items, addDefault);
           });
        }

        /// <summary>
        /// 根据Id获取户型图
        /// </summary>
        /// <param name="dto">字段 Id</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetHouseMapById([FromBody] IdDto dto)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                return await HouseMapService.GetHouseMapById(dto.Id);
            }));
        }

        /// <summary>
        /// 根据Id获取户型图
        /// </summary>
        /// <param name="dto">入参</param>
        /// <remarks>
        /// Code = 0，表示获取户型图成功
        /// Code != 0，表示户型图不存在或已删除
        /// </remarks>
        /// <returns></returns>
        [HttpPost, AllowAnonymous]
        [SwaggerResponse(0, "result字段为户型图Url", typeof(ApiResult))]
        public async Task<ApiResult> GetHouseMapBase([FromBody] IdDto dto)
        {
            return await HouseMapService.GetHouseMapBase(dto.Id);
        }

        /// <summary>
        /// 返回本项目的楼栋楼层树形数据
        /// </summary>
        /// <param name="obj">字段 Id</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetBuildingFloorTreeDataByProjectID(JObject obj)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                var Id = obj.GetAndCheck<Guid>("Id");
                var houseMapId = obj.GetAndCheck<Guid>("houseMapId");
                return await HouseMapService.GetBuildingFloorTreeDataByProjectID(Id, houseMapId);
            }));
        }

        [HttpPost]
        public async Task<ApiResult> GetSelectedBuildingFloorByHouseMap(JObject obj)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                var houseMapId = obj.GetAndCheck<Guid>("houseMapId");
                return await HouseMapService.GetSelectedBuildingFloorByHouseMap(houseMapId);
            }));
        }

        /// <summary>
        /// 删除户型图
        /// </summary>
        /// <param name="obj">字段 Id</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> RemoveHouseMap(JObject obj)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                var Id = obj.GetAndCheck<Guid>("Id");
                await HouseMapService.RemoveHouseMap(Id);
            }));
        }

        /// <summary>
        /// 删除户型图
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> RemoveHouseMaps(List<Guid> list)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                await HouseMapService.RemoveHouseMaps(list);
            }));
        }

        /// <summary>
        /// 获取获取项目下拉选项
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetProjectSelectItem()
        {
            return await TryCatchAsync(ProjectService.GetProjectSelectItem());
        }

        /// <summary>
        /// 首页项目统计
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetProjectForHome()
        {
            return await TryCatchAsync(ProjectService.GetProjectForHome());
        }

        #region 站点类型

        /// <summary>
        /// 取所有有效站点类型
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetAllPonitTypes(JObject obj)
        {
            var projectid = obj.GetAndCheck<Guid>("ProjectGuid");
            return await TryCatchAsync(ProjectService.GetAllPonitTypes(projectid));
        }

        /// <summary>
        /// 取所有有效站点类型
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> RemovePonitTypes(JObject obj)
        {
            return await TryCatchAsync(Task.Run(async () =>
            {
                var Id = obj.GetAndCheck<Guid>("Id");
                var projectid = obj.GetAndCheck<Guid>("ProjectGuid");
                await ProjectService.RemovePonitTypes(Id, projectid);
            }));
        }

        /// <summary>
        /// 保存当前站点类型
        /// V4.3修改：站点测量项默认不选中“天花平整度”
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> SavePointType(MsPointTypeDto obj)
        {
            await Contracts.Frequency($"user_SavePointType_limit_{TokenModel.Id}", 1, TimeSpan.FromSeconds(3), CommonLocalizer["YB0449"].Value);

            return await TryCatchAsync(Task.Run(async () =>
            {
                var name = obj.Name;
                var projectStandardId = obj.ProjectStandardId;
                if (string.IsNullOrWhiteSpace(name))
                {
                    throw new OperationException(Localizer["YB0012"]);
                }

                if (name.Length > 10)
                {
                    // 站点名称不能10字符和前端保持一致
                    throw new OperationException(Localizer["YB0140"]);
                }
                if (name.IsSpecialChars())
                {
                    // 站点名称不能包含特殊字符
                    throw new OperationException(Localizer["YB0139"]);
                }

                await ProjectService.SavePointType(name, obj.ProjectGuid);
                return await ProjectService.GetPointTypeDetails(projectStandardId, obj.ProjectGuid);
            }));
        }

        #endregion 站点类型

        /// <summary>
        /// 作者：黄钧航
        /// 提供FMS-获取所有项目信息
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetAllProjects()
        {
            return await TryCatchAsync(ProjectService.GetAllProjects());
        }

        /// <summary>
        /// 获取项目列表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult> GetProjecList(MsProjectCondition model)
        {
            return await TryCatchAsync(ProjectService.GetProjectWithReportPage(model));
        }

        /// <summary>
        /// 通过户型图ID下载Dxf文件
        /// </summary>
        /// <param name="idDto">户型图ID</param>
        /// <returns>Dxf文件相对路径</returns>
        [HttpPost]
        public async Task<ApiResult> DownloadDxfById(IdDto idDto)
        {
            return await HouseMapService.GetHouseMapDxf(idDto.Id);
        }
    }
}